#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
定义存储处理
"""
import setting
import pymongo
from pymongo import ReturnDocument
from pymongo import ASCENDING


class mongo_client(object):
    """
    mongodb数据库连接，使用单例模式，避免创建过多连接
    """
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        client= pymongo.MongoClient('mongodb://'+setting.MONGODB_HOST+':'+setting.MONGODB_PORT)
        db = client[setting.MONGODB_DB_NAME]
        db.authenticate(setting.MONGODB_USER, setting.MONGODB_PASSWORD)
        self.db = db

    def __call__(self, *args, **kwargs):
        if self.db is None:
            self.db = super().__call__(*args, **kwargs)
            return self.db
        else:
            return self.db


class user (object):
    """
    用户数据:
        {
            "uid":用户id,
            "username":用户名,
            "thumb":用户头像,
        }
    """
    def __init__(self):
        mongocli = mongo_client()
        self.db = mongocli.db.user

    async def get(self, user_info=None):
        info = {}
        if not user_info:
            return info

        # 根据uid查询用户数据
        if 'uid' in user_info and (user_info['uid']):
            result = self.db.find_one({'uid': user_info['uid']})
            if result:
                info = result
                return info
        elif 'username' in user_info and (user_info['username']):
            result = self.db.find_one({'username': user_info['username']})
            if result:
                info = result
                return info

        return info

    async def save(self, user_info=None):
        if not user_info:
            return False

        status = False
        # 检测是否存在uid对应数据,不存在则新建
        if 'uid' in user_info and user_info['uid']:
            result = self.db.find_one({'uid': user_info['uid']}, {'uid': 1})
            if result:
                status = self.db.update_one({'uid': user_info['uid']}, {'$set': user_info})
            else:
                status = self.db.insert(user_info)
        # 对于早期的ip党按用户名进行唯一性检测
        elif 'username' in user_info and (not user_info['uid']) and user_info['username']:
            result = self.db.find_one({'username': user_info['username']}, {'uid': 1, 'username': 1})
            if not result:
                status = self.db.insert(user_info)
            else:
                status = True
        if status:
            return True
        else:
            return False


class comment(object):
    """
    评论数据:
        {
            "tid":贴子id,
            "pid":父级id,即回复了哪个
            "comment_id":回复id,
            "content":回复内容,
            "username":用户名,
            "uid",回复用户id,若为ip党则留空,
            "date":发表时间,
        }
    """
    def __init__(self):

        mongocli = mongo_client()
        self.db = mongocli.db.comment

    async def get(self, comment_info=None):
        info = {}
        if not comment_info:
            return info

        # 根据comment_id查询评论数据
        if 'comment_id' in comment_info and (comment_info['comment_id']):
            result = self.db.find_one({'comment_id': comment_info['comment_id']})
            if result:
                info = result
                return info

        return info

    async def save(self, comment_info=None):
        if not comment_info:
            return False

        status = False
        # 检测是否存在comment_id对应数据,不存在则新建
        if 'comment_id' in comment_info and comment_info['comment_id']:
            result = self.db.find_one({'comment_id': comment_info['comment_id']}, {'comment_id': 1})
            if not result:
                status = self.db.insert(comment_info)
        if status:
            return True
        else:
            return False


class relationship(object):
    """
    用户回复之间的关系指数，以每一个回贴对当页用户的影响指数为1,以此叠加
    {
        'from':发贴用户username,
        'to':相关用户username,
        'count':指数,
    }
    """
    def __init__(self):
        mongocli = mongo_client()
        self.db = mongocli.db.relationship

    async def get(self, relationship_info=None):
        info = {}
        if not relationship_info:
            return info

        # 根据from to查询
        if 'from' in relationship_info and (relationship_info['from']) and 'to' in relationship_info and (relationship_info['to']):
            result = self.db.find_one({'from': relationship_info['from'], 'to': relationship_info['to']})
            if result:
                info = result

        return info

    async def save(self, relationship_info=None):
        if not relationship_info:
            return False

        status = False
        # 检测是否存在对应数据,不存在则新建
        if 'from' in relationship_info and (relationship_info['from']) and 'to' in relationship_info and (relationship_info['to']):
            result = self.db.find_one({'from': relationship_info['from'], 'to': relationship_info['to']}, {'_id': 1})
            if result:
                status = self.db.update_one({'from': relationship_info['from'], 'to': relationship_info['to']}, {'$inc': {'count': int(relationship_info['count'])}})
            else:
                status = self.db.insert({'from': relationship_info['from'], 'to': relationship_info['to'], 'count': int(relationship_info['count'])})
        if status:
            return True
        else:
            return False

    async def get_top(self, rate=1000, length=20):
        relationship_list = []
        sort = [("count", -1)]
        result = self.db.find({'count': {'$gt': rate}}, sort=sort, limit=length)
        for relationship in result:
            relationship['_id'] = str(relationship['_id'])
            relationship_list.append(relationship)

        return relationship_list

    async def get_list(self, search_params, skip=0, limit=5, sort=[]):
        relationship_list = []
        if not sort:
            sort.append(('count', -1))
        result = self.db.find(search_params, skip=skip, limit=limit, sort=sort, allow_partial_results=True)
        for relationship in result:
            relationship['_id'] = str(relationship['_id'])
            relationship_list.append(relationship)
        return relationship_list


class crawl_task(object):
    """
    采集任务
    {
        '_id':任务id,
        'type':paging分页,topic贴子,
        'url':任务url,
        'title':url标题
        'status':0未运行,1被领取,2完成,-1失败
    }
    """
    def __init__(self):
        mongocli = mongo_client()
        self.db = mongocli.db.crawl_task

    async def get(self, crawl_task_info=None):
        info = {}
        if not crawl_task_info:
            return info

        # 根据_id查询
        if '_id' in crawl_task_info and (crawl_task_info['_id']):
            result = self.db.find_one({'_id': crawl_task_info['_id']})
            if result:
                info = result
                return info

        # 根据任务类型获取信息
        if 'type' in crawl_task_info and (crawl_task_info['type']):
            result = self.db.find_one({'type': crawl_task_info['type'], 'status': 0})
            if result:
                info = result
                return info

        return info
    async def pop_one_task(self, crawl_task_info):
        info = {}
        if not crawl_task_info:
            return info

        if 'type' in crawl_task_info and (crawl_task_info['type']):
            result = self.db.find_one_and_update({'type': crawl_task_info['type'], 'status': 0}, {'$set': {'status': 1}}, upsert=False, return_document=ReturnDocument.AFTER)
            if result:
                info = result

        return info

    async def save(self, crawl_task_info=None):
        if not crawl_task_info:
            return False

        status = False
        if '_id' in crawl_task_info and crawl_task_info['_id']:
            status = self.db.update_one({'_id': crawl_task_info['_id']}, {'$set': crawl_task_info})
        # 检测是否存在url对应数据,不存在则新建
        elif 'url' in crawl_task_info and crawl_task_info['url']:
            result = self.db.find_one({'type': crawl_task_info['type'], 'url': crawl_task_info['url']}, {'_id': 1})
            if result:
                status = self.db.update_one({'_id': result['_id']}, {'$set': crawl_task_info})
            else:
                if not ('status' in crawl_task_info):
                    crawl_task_info['status'] = 0
                status = self.db.insert(crawl_task_info)
        if status:
            return True
        else:
            return False
